﻿#include "GMallManager.h"
#include "Character/Player.h"
#include "Character/PlayerMgr.h"
#include "LogicService.h"
#include "Mail/GMailManager.h"
#include "Common/Item/ItemMgr.h"
#include "Duplicate/DuplicateMgr.h"
#include "Character/drop/DropMgr.h"
#include "Common/TableDataEx/ItemCfg.h"
#include "Common/TableData/ExchangeExchangeCfg.h"
#include "Common/TableData/ExchangeEquivalentCfg.h"

using namespace ProtoBuf;

GMallManager::GMallManager()
{

}

GMallManager::~GMallManager()
{

}

bool GMallManager::Init()
{
	IMessageDispatch *pMessageDispatch = g_GetLogicService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		return false;
	}
	pMessageDispatch->registerClientHandler(EMODULE_ID_MALL, this);
	pMessageDispatch->registerServerHandler(EMODULE_ID_MALL, this);

	return true;
}

void GMallManager::UnInit()
{
	IMessageDispatch *pMessageDispatch = g_GetLogicService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		return;
	}
	pMessageDispatch->unregisterClientHandler(EMODULE_ID_MALL);
	pMessageDispatch->unregisterServerHandler(EMODULE_ID_MALL);
}

void GMallManager::onClientMessage(uint32_t actionId, RECV_PACKAGE& package, uint64_t Id /* = 0 */)
{
	switch (actionId)
	{
	case CLIENT_TO_LOGIC_BUY:
		Buy(package, Id);
		break;
	case CLIENT_TO_LOGIC_SELL:
		Sell(package, Id);
		break;
	case CLIENT_TO_LOGIC_EXCHANGE:
		Exchange(package, Id);
		break;
	case CLIENT_TO_LOGIC_HANDSEL:
		Handsel(package, Id);
		break;
	default:
		break;
	}
}

void GMallManager::onServerMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case CENTER_TO_LOGIC_BUY_VERIFY_RSP:
		DoBuyVerifyRsp(package);
		break;
	case CENTER_TO_LOGIC_SELL_VERIFY:
		DoSellVerifyRsp(package);
		break;
	case CENTER_TO_LOGIC_HANDSEL_VERIFY:
		DoHandselVerifyRsp(package);
		break;
	default:
		break;
	}
}

void GMallManager::Buy(RECV_PACKAGE &package, CharIDType Id)
{
	Mall_BuyReq buyReq;
	Mall_Buy_VerifyReq verifyReq;

	if (!buyReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Buy Mall_BuyReq parse failed...");
		return;
	}

	//Player * pPlayer = g_GetCreatureMgr()->GetPlayer(buyReq.char_id());
	Player * pPlayer = g_GetCreatureMgr()->GetPlayer(Id);
	if (nullptr == pPlayer)
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Buy but Player is nullptr cid:%lu ", buyReq.char_id());
		return;
	}
	if (ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState())
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Buy ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState() cid:%lu ", buyReq.char_id());
		return;
	}

	const MallMallCfgInfo* pMallCfgInfo = g_GetMallMallCfgTable()->GetMallMallCfgInfo(buyReq.mall_id());
	if (nullptr == pMallCfgInfo)
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Buy but pMallCfgInfo is nullptr mall_id:%d", buyReq.mall_id());
		return;
	}
	
	if (!CheckPlayer(pPlayer, pMallCfgInfo))
	{
		return;
	}

	if (!CheckMoney(pPlayer, pMallCfgInfo, buyReq.count()))
	{
		return;
	}

	//背包满了发邮件,所以这里不检查
	//if (!CheckPackage(pPlayer, pMallCfgInfo, buyReq.count()))
	//{
	//	return;
	//}

	uint32_t fund = 0;
	if (!CheckRunBus_buy(pPlayer, pMallCfgInfo, fund))
	{
		return;
	}

	if (!CheckGoods(pPlayer, pMallCfgInfo, buyReq.count()))
	{
		return;
	}

	verifyReq.set_fund(fund);
	verifyReq.set_char_id(pPlayer->GetId());
	verifyReq.set_mall_id(buyReq.mall_id());
	verifyReq.set_count(buyReq.count());
	//发消息到中心服验证
	if (!g_GetLogicService()->SendDataToCenter(EMODULE_ID_MALL, LOGIC_TO_CENTER_BUY_VERIFY_REQ, &verifyReq))
	{
		LogErrFmtPrint("[logic] GMallManager::Buy SendDataToCenter failed...cid:%lu,mallid:%d ", buyReq.char_id(), buyReq.mall_id());
	}
}

void GMallManager::Sell(RECV_PACKAGE &package, CharIDType Id)
{
	Player* pPlayer = (Player*)g_GetCreatureMgr()->GetPlayer(Id); // package.session->GetUserData().ptr;
	if (nullptr == pPlayer)
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Buy but pPlayer is nullptr Id:%lu ", Id);
		return;
	}

	Mall_SellReq sellReq;
	if (!sellReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Sell Mall_SellReq parse failed...");
		return;
	}

	PackagePart *pPackage = dynamic_cast<PackagePart*>(pPlayer->GetPart(PART_PACKAGE));
	if (nullptr == pPackage)
	{
		MMOLOG_FMT_DEBUG("[logic] GMallManager::Sell pPackage part is nullptr charId=%lu", Id);
		return;
	}

	const MallMallCfgInfo* pMallCfgInfo = g_GetMallMallCfgTable()->GetMallMallCfgInfo(sellReq.mall_id());
	if (nullptr == pMallCfgInfo)
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Sell but pMallCfgInfo is nullptr mall_id:%d", sellReq.mall_id());
		Mall_SellRsp sellRsp;
		sellRsp.set_retcode(RET_CONFIG_ERROR);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_SELL, &sellRsp);
		return;
	}

	//CItemBase *pItem = pPackage->GetItemByIndex(sellReq.item_idx());
	const CItemBase *pItem = pPackage->GetItem(sellReq.item_idx());
	if (nullptr == pItem || sellReq.count() <= 0 || pItem->GetNum() < sellReq.count())
	{
		Mall_SellRsp sellRsp;
		sellRsp.set_retcode(RET_FAIL);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_SELL, &sellRsp);
		return;
	}

	if ((uint32_t)pMallCfgInfo->itemID != pItem->GetItemID())
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Sell but error because mall_item_id:%u != itemid:%u", pMallCfgInfo->itemID, pItem->GetItemID());
		Mall_SellRsp sellRsp;
		sellRsp.set_retcode(RET_CONFIG_ERROR);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_SELL, &sellRsp);
		return;
	}

	//发消息到中心服验证
	Mall_Sell_VerifyReq verify;
	verify.set_char_id(Id);
	verify.set_mall_id(sellReq.mall_id());
	verify.set_item_idx(sellReq.item_idx());
	verify.set_count(sellReq.count());

	if (!CheckRunBus_sell(pPlayer, pMallCfgInfo, verify))
	{
		return;
	}
	
	if (!g_GetLogicService()->SendDataToCenter(EMODULE_ID_MALL, LOGIC_TO_CENTER_SELL_VERIFY, &verify))
	{
		LogErrFmtPrint("[logic] GMallManager::Sell SendDataToCenter failed...");
	}
}

void GMallManager::Exchange(RECV_PACKAGE &package, CharIDType Id)
{
	Mall_ExchangeReq exchangeReq;
	if (!exchangeReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Exchange Mall_ExchangeReq parse failed...");
		return;
	}
	//
	Player* pPlayer = (Player*)g_GetCreatureMgr()->GetPlayer(Id); // package.session->GetUserData().ptr;
	if (nullptr == pPlayer)
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Exchange but pPlayer is nullptr charId:%lu", Id);
		return;
	}
	if (ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState())
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Exchange ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState() charId:%lu", Id);
		return;
	}

	PackagePart *pPackage = dynamic_cast<PackagePart*>(pPlayer->GetPart(PART_PACKAGE));
	if (nullptr == pPackage)
	{
		MMOLOG_FMT_DEBUG("[logic] GMallManager::Exchange pPackage part is nullptr charId=%lu", Id);
		return;
	}	

	Mall_ExchangeRsp exchangeRsp;
	const ExchangeExchangeCfgInfo *exchangeCfg = g_GetExchangeExchangeCfgTable()->GetExchangeExchangeCfgInfo(exchangeReq.exchange_id());
	if (nullptr == exchangeCfg)
	{
		exchangeRsp.set_retcode(RET_CONFIG_ERROR);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_EXCHANGE, &exchangeRsp);
		return;
	}

	bool result = false;
	LIST_ITEM addItems;
	for (VecExchangeExchangePlanCfg::const_iterator iter = exchangeCfg->vecExchangeExchangePlanCfg.begin(); iter != exchangeCfg->vecExchangeExchangePlanCfg.end(); ++iter)
	{
		if ((*iter).Id <= 0)						continue;
		const ExchangeEquivalentCfgInfo *equivalCfg = g_GetExchangeEquivalentCfgTable()->GetExchangeEquivalentCfgInfo((*iter).Id);
		if (nullptr == equivalCfg)					continue;
		addItems.clear();
		for (VecExchangeEquivalentItemCfg::const_iterator it = equivalCfg->vecExchangeEquivalentItemCfg.begin(); it != equivalCfg->vecExchangeEquivalentItemCfg.end(); it++)
		{
			if ((*it).Id <= 0 || (*it).Num <= 0)	continue;
			SItem item;
			item.nItemID = (*it).Id;
			item.nNum = (*it).Num;
			addItems.push_back(item);
		}
		if (addItems.size() > 0 && pPackage->HasItem(addItems))
		{
			result = true;
			break;
		}
	}
	
	if (!result)
	{
		exchangeRsp.set_retcode(RET_MALL_EXCHANGE_ERROR);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_EXCHANGE, &exchangeRsp);
		return;
	}

	VEC_INT32 boxIdList;
	boxIdList.push_back(exchangeCfg->awardId);
	SItemSourceParam sourceParam;
	ERetCode retcode = g_GetDropMgr()->PlayerAddBox(pPlayer, boxIdList, sourceParam);
	
	if (retcode == RET_SUCCESS)
	{
		sourceParam.source = S_MALL_Exchange;
		pPackage->RemoveItem(addItems, sourceParam);
	}
		

	exchangeRsp.set_retcode(retcode);
	pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_EXCHANGE, &exchangeRsp);
}


void GMallManager::Handsel(RECV_PACKAGE &package, CharIDType Id)
{
	Mall_HandselReq req;
	if (!req.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Handsel Mall_HandselReq parse failed...");
		return;
	}

	Player* pPlayer = (Player*)g_GetCreatureMgr()->GetPlayer(Id);
	if (nullptr == pPlayer)
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Handsel but pPlayer is nullptr charId:%lu", Id);
		return;
	}
	if (ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState())
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Handsel ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState() charId:%lu", Id);
		return;
	}
	//cid
	if (Id == req.target_id())
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Handsel Id == req.target_id()  charId:%lu ", Id);
		return;
	}
	//数量
	if (req.count() <= 0)
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Handsel req.count() <= 0  charId:%lu,count:%u ", Id, req.count());
		return;
	}
	const MallMallCfgInfo* pMallCfgInfo = g_GetMallMallCfgTable()->GetMallMallCfgInfo(req.mall_id());
	if (nullptr == pMallCfgInfo)
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::Handsel but pMallCfgInfo is nullptr mall_id:%d", req.mall_id());
		Mall_HandselRsp rsp;
		rsp.set_retcode(RET_CONFIG_ERROR);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_HANDSEL, &rsp);
		return;
	}

	//检查赠送角色货币
	if (!CheckMoney(pPlayer, pMallCfgInfo, req.count(), true))
	{
		return;
	}

	//中心服验证
	Mall_Handsel_VerifyReq verify;
	verify.set_char_id(pPlayer->GetId());
	verify.set_mall_id(req.mall_id());
	verify.set_count(req.count());
	verify.set_target_id(req.target_id());
	verify.set_msg(req.msg());
	if (!g_GetLogicService()->SendDataToCenter(EMODULE_ID_MALL, LOGIC_TO_CENTER_HANDSEL_VERIFY, &verify))
	{
		LogErrFmtPrint("[logic] GMallManager::Handsel SendDataToCenter failed...cid:%lu ", Id);
	}
}

bool GMallManager::CheckPlayer(Player* pPlayer, const MallMallCfgInfo* pMallCfgInfo)
{
	bool result = true;
	ERetCode retCode = RET_SUCCESS;

	if ((int32_t)pPlayer->GetAttr(C_LEVEL) < pMallCfgInfo->levelLimit)
	{
		result = false;
		retCode = RET_LEVEL_LACK;
	}
	else if ((int32_t)pPlayer->GetAttr(C_VIP) < pMallCfgInfo->vipLimit)
	{
		result = false;
		retCode = RET_VIP_LEVEL_LACK;
	}
	else if (pMallCfgInfo->moneyType == Mall_MoneyType_GuildContri && pPlayer->GetAttr(C_UNION_ID) <= 0)
	{
		result = false;
		retCode = RET_UNION_NOT_JOIN;
	}

	if (!result)
	{
		Mall_BuyRsp buyRsp;
		buyRsp.set_retcode(retCode);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_BUY_RESULT, &buyRsp);
	}
	return result;
}

bool GMallManager::CheckMoney(Player* pPlayer, const MallMallCfgInfo* pMallCfgInfo, uint32_t count, bool isHandsel)
{
	bool enough = false;
	ERetCode retCode = RET_FAIL;
	int64_t needMoney = (pMallCfgInfo->discount <= 0) ? (pMallCfgInfo->price * count) : (pMallCfgInfo->price * pMallCfgInfo->discount / 100.f * count);

	if (pMallCfgInfo->moneyType == Mall_MoneyType_Gold/*C_GOLD*/)
	{
		enough = (pPlayer->GetAttr(C_GOLD) >= needMoney);
		retCode = RET_GOLD_LACK;
	}
	else if (pMallCfgInfo->moneyType == Mall_MoneyType_Diamond/*C_DIAMOND*/)
	{
		enough = (pPlayer->GetAttr(C_DIAMOND) >= needMoney);
		retCode = RET_DIAMOND_LACK;
	}
	else if (pMallCfgInfo->moneyType == Mall_MoneyType_BindDiamond/*C_DIAMOND_BIND*/)
	{
		enough = ((pPlayer->GetAttr(C_DIAMOND) + pPlayer->GetAttr(C_DIAMOND_BIND)) >= needMoney);
		retCode = RET_BIND_DIAMOND_LACK;
	}
	else if (pMallCfgInfo->moneyType == Mall_MoneyType_ContriCoin/*C_CAMP_COIN*/)
	{
		enough = (pPlayer->GetAttr(C_CAMP_COIN) >= needMoney);
		retCode = RET_CAMP_COIN_LACK;
	}
	else if (pMallCfgInfo->moneyType == Mall_MoneyType_GuildContri)
	{
		enough = true;
	}
	else if (pMallCfgInfo->moneyType == Mall_MoneyType_ArenaScore/*C_ARENA_SCORE*/)
	{
		enough = (pPlayer->GetAttr(C_ARENA_SCORE) >= needMoney);
		retCode = RET_ARENA_SCORE_LACK;
	}
	else if (pMallCfgInfo->moneyType == Mall_MoneyType_RunBusFund)
	{
		enough = true;
	}
	else if (pMallCfgInfo->moneyType == Mall_MoneyType_DuplicateCoin)
	{
		const MallMalltypeCfgInfo* mallTypeCfg = g_GetMallMalltypeCfgTable()->GetMallMalltypeCfgInfo(pMallCfgInfo->mallType);
		if (mallTypeCfg)
		{
			VEC_INT32 duplicateList;
			StringSplit2Int(mallTypeCfg->groupParam, ';', duplicateList);
			IDuplicate *pDupli = g_GetDuplicateMgr()->GetDuplicate(pPlayer->GetSceneId());
			if (pDupli /*&& !pDupli->IsEnd()*/)
			{
				VEC_INT32::iterator iterOpen = std::find(duplicateList.begin(), duplicateList.end(), pDupli->GetDuplicateID());
				if (iterOpen != duplicateList.end())
				{
					enough = (pDupli->GetExploit(pPlayer->GetCid()) >= (int32_t)needMoney);
				}
			}
		}
		retCode = RET_MALL_EXPLOIT_LACK;
	}

	if (!enough && !isHandsel)
	{
		Mall_BuyRsp buyRsp;
		buyRsp.set_retcode(retCode);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_BUY_RESULT, &buyRsp);
	}
	if (!enough && isHandsel)
	{
		Mall_HandselRsp handselRsp;
		handselRsp.set_retcode(retCode);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_HANDSEL, &handselRsp);
	}

	return enough;
}

bool GMallManager::CheckGoods(Player* pPlayer, const MallMallCfgInfo* pMallCfgInfo, uint32_t count)
{
	//若购买普通商品(无任何购买和销售限制)，不必经中心服验证，直接逻辑服处理返回
	const MallMalltypeCfgInfo* mallTypeCfg = g_GetMallMalltypeCfgTable()->GetMallMalltypeCfgInfo(pMallCfgInfo->mallType);
	if (mallTypeCfg && (mallTypeCfg->groupType == 1/*商城类型(商城主面板)*/ || pMallCfgInfo->moneyType == Mall_MoneyType_ArenaScore/*竞技场商城*/) && pMallCfgInfo->buyAmount <= 0 && pMallCfgInfo->goodsAmount <= 0)
	{
		CostMoney(pPlayer, pMallCfgInfo, count);
		AddItem(pPlayer, pMallCfgInfo, count);

		Mall_BuyRsp buyRsp;
		buyRsp.set_retcode(RET_SUCCESS);
		buyRsp.set_mall_id(pMallCfgInfo->id);
		buyRsp.set_count(count);
		buyRsp.set_item_id(pMallCfgInfo->itemID);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_BUY_RESULT, &buyRsp);
		return false;
	}
	return true;
}

bool GMallManager::CheckRunBus_buy(Player* pPlayer, const MallMallCfgInfo* pMallCfgInfo, uint32_t &fund)
{
	//把跑商当前资金带到中心服 因为跑商商品的价格存在中心服 而不是读配置
	if (pMallCfgInfo->moneyType != Mall_MoneyType_RunBusFund)
	{
		return true;
	}

	Part* pPart = pPlayer->GetPart(PART_PACKAGE);
	if (nullptr == pPart)
	{
		MMOLOG_FMT_DEBUG("[logic] GMallManager::CheckRunBus_buy pPackage part is nullptr charId=%lu", pPlayer->GetId());
		return false;
	}

	const CItemBase* pItemBase = pPart->GetItemByType((int32_t)EItemSubType::EItemSubType_run_business);
	if (nullptr == pItemBase)
	{
		Mall_BuyRsp buyRsp;
		buyRsp.set_retcode(RET_MALL_RUN_FUND_LACK);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_BUY_RESULT, &buyRsp);
		return false;
	}

	CItemBase* pItem = const_cast<CItemBase*>(pItemBase);
	if (nullptr == pItem)
	{
		Mall_BuyRsp buyRsp;
		buyRsp.set_retcode(RET_MALL_RUN_FUND_LACK);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_BUY_RESULT, &buyRsp);
		return false;
	}

	const VEC_INT32 *pvecPara = g_GetItemCfgMgr()->GetItemFuncParamCfg(pItemBase->GetItemID());
	if (nullptr == pvecPara)
	{
		Mall_BuyRsp buyRsp;
		buyRsp.set_retcode(RET_CONFIG_ERROR);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_BUY_RESULT, &buyRsp);
		return false;
	}

	if (pvecPara->size() < 1)
	{
		Mall_BuyRsp buyRsp;
		buyRsp.set_retcode(RET_CONFIG_ERROR);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_BUY_RESULT, &buyRsp);
		return false;
	}

	if (pItem->GetFund() >= pvecPara->at(0))	//{100000,40000} -> {目标资金,初始资金}
	{
		Mall_BuyRsp buyRsp;
		buyRsp.set_retcode(RET_MALL_FUNDBUS_BUY_ERROR);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_BUY_RESULT, &buyRsp);
		return false;
	}
	fund = pItem->GetFund();
	return true;
}

bool GMallManager::CheckRunBus_sell(Player* pPlayer, const MallMallCfgInfo* pMallCfgInfo, Mall_Sell_VerifyReq &req/*, uint32_t count*/)
{
	//跑商商品出售时  现有资金超过目标资金不能出售
	if (pMallCfgInfo->moneyType != Mall_MoneyType_RunBusFund)
	{
		return true;
	}

	Part* pPart = pPlayer->GetPart(PART_PACKAGE);
	if (nullptr == pPart)
	{
		MMOLOG_FMT_DEBUG("[logic] GMallManager::CheckRunBus_sell pPackage part is nullptr charId=%lu", pPlayer->GetId());
		return false;
	}

	const CItemBase* pItemBase = pPart->GetItemByType((int32_t)EItemSubType::EItemSubType_run_business);
	if (nullptr == pItemBase)
	{
		Mall_SellRsp sellRsp;
		sellRsp.set_retcode(RET_MALL_RUN_FUND_ITEM_LACK);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_SELL, &sellRsp);
		return false;
	}

	CItemBase* pItem = const_cast<CItemBase*>(pItemBase);
	if (nullptr == pItem)
	{
		Mall_SellRsp sellRsp;
		sellRsp.set_retcode(RET_MALL_RUN_FUND_ITEM_LACK);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_SELL, &sellRsp);
		return false;
	}

	//检查现有资金是否超过目标资金
	int32_t fund = pItemBase->GetFund();
	const VEC_INT32 *pvecPara = g_GetItemCfgMgr()->GetItemFuncParamCfg(pItemBase->GetItemID());
	if (nullptr == pvecPara)
	{
		Mall_SellRsp sellRsp;
		sellRsp.set_retcode(RET_CONFIG_ERROR);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_SELL, &sellRsp);
		return false;
	}
	if (pvecPara->size() < 1)
	{
		Mall_SellRsp sellRsp;
		sellRsp.set_retcode(RET_CONFIG_ERROR);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_SELL, &sellRsp);
		return false;
	}

	/*if (fund >= pvecPara->at(0))	//{100000,40000} -> {目标资金,初始资金}
	{
		Mall_SellRsp sellRsp;
		sellRsp.set_retcode(RET_MALL_FUNDBUS_SELL_ERROR);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_SELL, &sellRsp);
		return false;
	}*/
	req.set_money(fund);
	req.set_g_money(pvecPara->at(0));
	return true;
}

bool GMallManager::CheckPackage(Player* pPlayer, const MallMallCfgInfo* pMallCfgInfo, uint32_t count)
{
	LIST_ITEM lstAddItem;
	SItem item;
	item.nItemID = pMallCfgInfo->itemID;
	item.nNum = count;
	lstAddItem.push_back(item);

	Part *pPackage = pPlayer->GetPart(PART_PACKAGE);
	if (nullptr == pPackage)
	{
		MMOLOG_FMT_DEBUG("[logic] GMallManager::CheckPackage pPackage part is nullptr charId=%lu", pPlayer->GetId());
		return false;
	}

//	if (!pPackage->CanAddItem(lstAddItem) == false)
//	{
// 		Mall_BuyRsp buyRsp;
// 		buyRsp.set_retcode(1);
// 		pPlayer->SendDataToClientEx(EMODULE_ID_MALL, LOGIC_TO_CLIENT_BUY_RESULT, &buyRsp);
// 		return false;
//	}
	return true;
}

int64_t GMallManager::CostMoney(Player* pPlayer, const MallMallCfgInfo* pMallCfgInfo, uint32_t count, bool isHandsel)
{
	bool needStatistics = false;
	bool isDisCount = false;
	MallLogInfo malllog;

	isDisCount = pMallCfgInfo->discount > 0;
	int64_t price = isDisCount ? (pMallCfgInfo->price * pMallCfgInfo->discount / 100.f) : pMallCfgInfo->price;
	int64_t needMoney = price * count;

	if (pMallCfgInfo->moneyType == Mall_MoneyType_Gold/*C_GOLD*/)
	{
		//pPlayer->AddAttr(C_GOLD, -1*(int64_t)needMoney, true);
		pPlayer->AddSourceAttr(C_GOLD, -1 * (int64_t)needMoney, true, S_MALL_BUY);
		needStatistics = true;
		malllog.costMap.insert(make_pair(C_GOLD, needMoney));
	}
	else if (pMallCfgInfo->moneyType == Mall_MoneyType_Diamond/*C_DIAMOND*/)
	{
		//pPlayer->AddAttr(C_DIAMOND, -needMoney, true);
		pPlayer->AddSourceAttr(C_DIAMOND, -needMoney, true, S_MALL_BUY);
		needStatistics = true;
		malllog.costMap.insert(make_pair(C_DIAMOND, needMoney));
	}
	else if (pMallCfgInfo->moneyType == Mall_MoneyType_BindDiamond/*C_DIAMOND_BIND*/)
	{
		//int32_t curDiamond = pPlayer->GetAttr(C_DIAMOND);
		int32_t curDiamondBind = pPlayer->GetAttr(C_DIAMOND_BIND);
		if (curDiamondBind >= needMoney)
		{
			//pPlayer->AddAttr(C_DIAMOND_BIND, -needMoney, true);
			pPlayer->AddSourceAttr(C_DIAMOND_BIND, -needMoney, true, S_MALL_BUY);
			malllog.costMap.insert(make_pair(C_DIAMOND_BIND, needMoney));
		}
		else   //绑钻不够
		{
			//pPlayer->AddAttr(C_DIAMOND_BIND, -curDiamondBind, true);
			pPlayer->AddSourceAttr(C_DIAMOND_BIND, -curDiamondBind, true, S_MALL_BUY);
			//pPlayer->AddAttr(C_DIAMOND, -(needMoney - curDiamondBind), true);
			pPlayer->AddSourceAttr(C_DIAMOND, -(needMoney - curDiamondBind), true, S_MALL_BUY);

			malllog.costMap.insert(make_pair(C_DIAMOND, needMoney - curDiamondBind));
			malllog.costMap.insert(make_pair(C_DIAMOND_BIND, curDiamondBind));
		}
		needStatistics = true;
	}
	else if (pMallCfgInfo->moneyType == Mall_MoneyType_GuildContri)
	{
		//公会贡献度已由中心服发起克扣
		needStatistics = true;
		malllog.costMap.insert(make_pair(C_UNION_CONTRI, needMoney));
	}
	else if (pMallCfgInfo->moneyType == Mall_MoneyType_ContriCoin)
	{
		//阵营军功币已由中心服发起克扣
		needStatistics = true;
		malllog.costMap.insert(make_pair(C_CAMP_SCORE, needMoney));
	}
	else if (pMallCfgInfo->moneyType == Mall_MoneyType_ArenaScore)
	{
		//pPlayer->AddAttr(C_ARENA_SCORE, -needMoney, true);
		pPlayer->AddSourceAttr(C_ARENA_SCORE, -needMoney, true, S_ARENA);
		needStatistics = true;
		malllog.costMap.insert(make_pair(C_ARENA_SCORE, needMoney));
	}
	else if (pMallCfgInfo->moneyType == Mall_MoneyType_DuplicateCoin)
	{
		IDuplicate *pDupli = g_GetDuplicateMgr()->GetDuplicate(pPlayer->GetSceneId());
		if (pDupli /*&& !pDupli->IsEnd()*/)
		{
			pDupli->BuyExploitItem(pPlayer->GetCid(), needMoney);
		}
	}
	if (needStatistics && !isHandsel)
	{
		const ItemItemCfgInfo *pItemCfg = g_GetItemItemCfgTable()->GetItemItemCfgInfo(pMallCfgInfo->itemID);
		if (pItemCfg == nullptr)
		{
			const EquipEquipCfgInfo *pEquipItemCfg = g_GetEquipEquipCfgTable()->GetEquipEquipCfgInfo(pMallCfgInfo->itemID);
			if (pEquipItemCfg != nullptr)
				malllog.itemName = pEquipItemCfg->name;
			else
				MMOLOG_FMT_ERROR("[logic] GMallManager::CostMoney not item and not equip...error itemID:%d", pMallCfgInfo->itemID);
		}
		else
			malllog.itemName = pItemCfg->name;

		malllog.count = count;
		malllog.itemId = pMallCfgInfo->itemID;
		malllog.price = price;
		malllog.discount = isDisCount;
		pPlayer->MallLog(malllog);
	}

	return needMoney;
}

void GMallManager::AddItem(Player* pPlayer, const MallMallCfgInfo* pMallCfgInfo, uint32_t count, int32_t money)
{
	//int8_t byType = EItemType_common;
	string ItemName = "";
	const ItemItemCfgInfo *pItemCfg = g_GetItemItemCfgTable()->GetItemItemCfgInfo(pMallCfgInfo->itemID);
	if (pItemCfg == nullptr)
	{
		const EquipEquipCfgInfo *pEquipItemCfg = g_GetEquipEquipCfgTable()->GetEquipEquipCfgInfo(pMallCfgInfo->itemID);
		if (pEquipItemCfg == nullptr)
		{
			MMOLOG_FMT_ERROR("[logic] GMallManager::AddItem pEquipItemCfg pItemCfg is nullptr itemID:%d", pMallCfgInfo->itemID);
			return;
		}
		ItemName = pEquipItemCfg->name;
		//byType = EItemType_equip;
	}
	else
		ItemName = pItemCfg->name;

	PackagePart *pPackage = dynamic_cast<PackagePart*>(pPlayer->GetPart(PART_PACKAGE));
	if (nullptr == pPackage)
	{
		MMOLOG_FMT_DEBUG("[logic] GMallManager::AddItem pPackage part is nullptr charId=%lu", pPlayer->GetId());
		return;
	}

	/*if (pMallCfgInfo->isAutoUse == 1)		//购买后自动使用
	{
		CItemBase *pItem = g_GetItemMgr()->MakeItemObj(byType);
		if (nullptr != pItem)
		{
			SItemCond itemCond;
			g_GetDropMgr()->GetItemCond(pPlayer, itemCond, EItemInitAttrType_NpcShop);
			if (pItem->Init(0, pMallCfgInfo->itemID, itemCond, count))
				pPackage->Use(pItem);
			g_GetItemMgr()->FreeItemObj(pItem);
		}
		return;
	}*/

	LIST_ITEM addItems;
	addItems.clear();
	SItem item;
	item.nItemID = pMallCfgInfo->itemID;
	item.byBind = pMallCfgInfo->isMarkBind;
	item.nNum = count;
	addItems.push_back(item);
	//
	VEC_ITEM_PROTO_EX vecProtoEx;
	vecProtoEx.clear();
	VEC_ITEM_PROTO_EX vecProtoItemsOut;
	vecProtoItemsOut.clear();
	SItemCond itemCond;
	g_GetDropMgr()->GetItemCond(pPlayer, itemCond,EItemInitAttrType_NpcShop);
	g_GetItemMgr()->CreateItem(addItems, vecProtoEx, itemCond);
	SItemSourceParam sourceParam;
	sourceParam.source = S_MALL_BUY;
	if (!pPackage->AddItem(vecProtoEx, vecProtoItemsOut, sourceParam))
	{
		string mailTitle = "商城交易";
		char mailContent[256];
		snprintf(mailContent, sizeof(mailContent), "你在商城购买的道具[%s],请查收！", ItemName.c_str());
		g_GetGMailMgr()->SendSystemMail(pPlayer->GetId(), mailTitle, mailContent, 0, 0, 0, 0, 0, vecProtoEx);
	}
	else
	{
		if (pMallCfgInfo->isAutoUse)//购买后自动使用
		{
			//商城购买之后自动使用数量都是1个，策划保证不会配置批量使用的物品
			if (vecProtoItemsOut.size() > 0)
			{
				ItemProtoInfo &protoItem = vecProtoItemsOut.at(0);
				UseItemArgProto protoArg;
				//使用背包物品
				pPackage->UseItem(protoItem.index(), 1, protoArg);
			}
		}
		//计算跑商商品类购买均价 该字段无逻辑功能 纯前端显示 搞飞机。。
		if (pMallCfgInfo->moneyType == Mall_MoneyType_RunBusFund)
		{
			pPackage->SetRunAvePrice(count, money);
		}
	}
}

void GMallManager::DoBuyVerifyRsp(RECV_PACKAGE &package)
{
	Mall_Buy_VerifyRsp verifyRsp;
	Mall_BuyRsp buyRsp;

	if (!verifyRsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::DoBuyVerifyRsp verifyRsp parse failed...");
		return;
	}

	CharIDType charId = verifyRsp.char_id();
	Player* pPlayer = g_GetCreatureMgr()->GetPlayer(charId);
	if (nullptr == pPlayer)
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::DoBuyVerifyRsp but Player is nullptr charId:%lu", charId);
		return;
	}

	PackagePart *pPackage = dynamic_cast<PackagePart*>(pPlayer->GetPart(PART_PACKAGE));
	if (nullptr == pPackage)
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::DoBuyVerifyRsp nullptr == pPackage charId:%lu", charId);
		return;
	}

	buyRsp.set_retcode(verifyRsp.result());

	if (RET_SUCCESS != verifyRsp.result())
	{
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_BUY_RESULT, &buyRsp);
		return;
	}

	
	const MallMallCfgInfo* pMallCfgInfo = g_GetMallMallCfgTable()->GetMallMallCfgInfo(verifyRsp.mall_id());
	if (nullptr == pMallCfgInfo)
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::DoBuyVerifyRsp pMallCfgInfo is nullptr mall_id:%d", verifyRsp.mall_id());
		return;
	}

	buyRsp.set_mall_id(verifyRsp.mall_id());
	buyRsp.set_count(verifyRsp.count());
	buyRsp.set_item_id(pMallCfgInfo->itemID);

	CostMoney(pPlayer, pMallCfgInfo, verifyRsp.count());
	AddItem(pPlayer, pMallCfgInfo, verifyRsp.count(), verifyRsp.fund());

	//跑商的消耗资金是从中心服带过来的
	if (pMallCfgInfo->moneyType == Mall_MoneyType_RunBusFund)
	{
		const CItemBase* pItemBase = pPackage->GetItemByType((int32_t)EItemSubType::EItemSubType_run_business);
		if (pItemBase)
		{
			CItemBase* pItem = const_cast<CItemBase*>(pItemBase);
			if (pItem && pItem->GetFund() >= (int32_t)verifyRsp.fund())
			{
				pPackage->SetRunBusiness(pItem->GetIndex(), pItem->GetFund() - verifyRsp.fund());
			}
		}
		
	}

	pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_BUY_RESULT, &buyRsp);
}

void GMallManager::DoSellVerifyRsp(RECV_PACKAGE &package)
{
	Mall_Sell_VerifyRsp verifyRsp;
	Mall_SellRsp sellRsp;

	if (!verifyRsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::DoSellVerifyRsp verifyRsp parse failed...");
		return;
	}

	CharIDType charId = verifyRsp.char_id();
	Player* pPlayer = g_GetCreatureMgr()->GetPlayer(charId);
	if (nullptr == pPlayer)
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::DoSellVerifyRsp but Player is nullptr charId:%lu", charId);
		return;
	}

	sellRsp.set_retcode(verifyRsp.result());
	if (ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState())
	{
		sellRsp.set_retcode(RET_FAIL);
		LogErrFmtPrint("DoSellVerifyRsp....ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState()...cid:%lu ", charId);
	}
	else if (RET_SUCCESS == verifyRsp.result())
	{
		PackagePart *pPackage = dynamic_cast<PackagePart*>(pPlayer->GetPart(PART_PACKAGE));
		if (nullptr != pPackage)
		{
			SItemSourceParam soureParam;
			soureParam.source = S_MALL_BUY;
			pPackage->RemoveItemByIndex(verifyRsp.item_idx(), verifyRsp.count(), soureParam);
			const CItemBase* pItemBase = pPackage->GetItemByType((int32_t)EItemSubType::EItemSubType_run_business);
			if (nullptr != pItemBase)
			{
				CItemBase* pItem = const_cast<CItemBase*>(pItemBase);
				if (nullptr != pItem)
				{
					pPackage->SetRunBusiness(pItem->GetIndex(), pItem->GetFund() + verifyRsp.money());
				}
			}
		}
	}

	sellRsp.set_mall_id(verifyRsp.mall_id());
	sellRsp.set_count(verifyRsp.count());
	pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_SELL, &sellRsp);
}

void GMallManager::DoHandselVerifyRsp(RECV_PACKAGE &package)
{
	Mall_Handsel_VerifyRsp verifyRsp;
	Mall_HandselRsp handselRsp;

	if (!verifyRsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::DoHandselVerifyRsp verifyRsp parse failed...");
		return;
	}
	int32_t ret = verifyRsp.result();
	CharIDType charId = verifyRsp.char_id();
	Player* pPlayer = g_GetCreatureMgr()->GetPlayer(charId);
	if (nullptr == pPlayer)
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::DoHandselVerifyRsp but Player is nullptr charId:%lu,mailid:%u,count:%u,ret:%d ", charId, verifyRsp.mall_id(), verifyRsp.count(),ret);
		return;
	}
	if (ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState())
	{
		LogInfoFmtPrint("GMallManager::DoHandselVerifyRsp....ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState()..charId:%lu,mailid:%u,count:%u,ret:%d ", charId, verifyRsp.mall_id(), verifyRsp.count(), ret);
	}

	const MallMallCfgInfo* pMallCfgInfo = g_GetMallMallCfgTable()->GetMallMallCfgInfo(verifyRsp.mall_id());
	if (nullptr == pMallCfgInfo)
	{
		MMOLOG_FMT_ERROR("[logic] GMallManager::DoHandselVerifyRsp pMallCfgInfo is nullptr mall_id:%d, charId:%lu,count:%u,ret:%d ", verifyRsp.mall_id(), charId,verifyRsp.count(),ret);
		handselRsp.set_retcode(RET_CONFIG_ERROR);
		pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_HANDSEL, &handselRsp);
		return;
	}

	if (verifyRsp.result() == RET_SUCCESS)
	{
		//扣除货币
		int64_t cost = CostMoney(pPlayer, pMallCfgInfo, verifyRsp.count(), true);
		if (ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState())
		{
			LogInfoFmtPrint("GMallManager::DoHandselVerifyRsp11....ACCOUNT_GAME_STATE_SWITCH == pPlayer->GetAccountState()..charId:%lu,mailid:%u,count:%u,cost:%ld ", charId, verifyRsp.mall_id(), verifyRsp.count(), cost);
		}
	}

	handselRsp.set_retcode(verifyRsp.result());
	pPlayer->SendDataToClient(EMODULE_ID_MALL, LOGIC_TO_CLIENT_HANDSEL, &handselRsp);
}
